package com.sec.android.app.myfiles.module.local.category;

import android.content.Context;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.provider.MediaStore;
import android.text.TextUtils;

import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.info.FileType;
import com.sec.android.app.myfiles.info.MediaFile;
import com.sec.android.app.myfiles.info.MediaFile.MediaFileInfo;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.AbsFileListAdapterImp;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.CategoryType;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.navigation.NavigationInfo.NavigationMode;
import com.sec.android.app.myfiles.provider.DbTableInfo.COLUMN_ID;
import com.sec.android.app.myfiles.util.PreferenceUtils;
import com.sec.android.app.myfiles.widget.listview.AbsListViewImp;

import java.util.ArrayList;

public class CategoryListAdapterImp extends AbsFileListAdapterImp {
    private static String mDocumentSelection = null;

    private static final int INTERNAL_STORAGE_ID = 0x10001;
    private static final int PRIVATE_STORAGE_ID = 0x0000;

    protected int mPreTotCount = -1;
    protected String mBucketId = null;

    protected static final String BUCKET_ID_QUERY = " bucket_id = ? ";
    protected static final String BUCKET_ID_QUERY_WITH_AND = " AND bucket_id = ?";

    protected static final String AUDIO_QUERY = " media_type = " + MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO;
    protected static final String AUDIO_QUERY_WITH_AND = " media_type = " + MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO + " AND ";

    protected static final String DOCUMENT_QUERY = "is_doc = 1";

    public CategoryListAdapterImp(Context context, NavigationInfo navigationInfo, AbsListViewImp listView, Cursor c, int flags) {
        super(context, navigationInfo, listView, c, flags);

        if (mCurRecord instanceof CategoryFileRecord) {
            mBucketId = ((CategoryFileRecord) mCurRecord).getBucketId();
        }
    }

    @Override
    public String getSelection() {
        String ret = null;
        CategoryType categoryType = getCategoryType();
        StringBuilder sb = new StringBuilder();

        switch (categoryType) {
            case Image:
                sb.append(mTableInfo.getColumnName(COLUMN_ID.FILE_TYPE)).append('=')
                        .append(String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE));
                break;
            case Video:
                sb.append(mTableInfo.getColumnName(COLUMN_ID.FILE_TYPE)).append('=')
                        .append(String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO));
                break;
            case Audio:
                sb.append(AUDIO_QUERY);
                break;
            case Document:
                if (AppFeatures.isSupportDocumentType(mContext)) {
                    sb.append(DOCUMENT_QUERY);
                } else {
                    sb.append(getDocumentSelection());
                }
                break;
            case Apk:
                sb.append(MediaStore.Files.FileColumns.DATA).append(" LIKE '%.apk'");
                boolean showHidden = PreferenceUtils.getShowHiddenFiles(mContext);
                if (!showHidden) {
                    String path = CategoryDbTableInfo.getInstance().getColumnName(COLUMN_ID.PATH);
                    String name = CategoryDbTableInfo.getInstance().getColumnName(COLUMN_ID.NAME);

                    sb.append(" AND ((LOWER(").append(path).append(") NOT LIKE '%/.%')  AND NOT(").append(name).append(" LIKE '.%'))");
                }
                break;
        }

        String filter = getFilteredSelection();
        if (!TextUtils.isEmpty(filter)) {
            if (sb.length() > 0) {
                sb.append(" AND ");
            }
            sb.append(filter);
        }

        if (mNavigationInfo.getMaxSelectCnt() == -1 && mNavigationInfo.getNavigationMode() == NavigationMode.Pick_files) {
            if (sb.length() > 0) {
                sb.append(" AND ");
            }
            sb.append(mTableInfo.getColumnName(COLUMN_ID.PATH)).append(" NOT LIKE ?");
        }


        if (mBucketId != null) {
            if (sb.length() > 0) {
                sb.append(BUCKET_ID_QUERY_WITH_AND);
            } else {
                sb.append(BUCKET_ID_QUERY);
            }
        }

        if (sb.length() > 0) {
            ret = sb.toString();
        }
        return ret;
    }

    private String getFilteredSelection() {
        String[] mimeTypeList = mNavigationInfo.getMimeTypeFilter();
        String[] extensionList = mNavigationInfo.getExtensionFilter();
        String colPath = mTableInfo.getColumnName(COLUMN_ID.PATH);
        String colMimeType = mTableInfo.getColumnName(COLUMN_ID.MIME_TYPE);
        String colFormat = mTableInfo.getColumnName(COLUMN_ID.FORMAT);
        String startPath = mNavigationInfo.getPathFilter();
        String prefix = mNavigationInfo.getPrefixFilter();

        StringBuilder sb = new StringBuilder();
        int cnt = 0;
        if (mimeTypeList != null && mimeTypeList.length > 0) {
            ArrayList<MediaFileInfo> infoList = null;
            sb.append("(");
            for (String mimeType : mimeTypeList) {
                if (infoList == null) {
                    infoList = MediaFile.getMimeTypeFileInfo(mimeType);
                } else {
                    infoList.addAll(MediaFile.getMimeTypeFileInfo(mimeType));
                }
            }
            if (infoList != null && !infoList.isEmpty()) {
                sb.append("(").append(colMimeType).append(" IS NULL AND ( ");
                for (MediaFileInfo mediaInfo : infoList) {
                    if ("MID_A".equals(mediaInfo.extension)) {
                        continue;
                    }
                    if (cnt != 0) {
                        sb.append(" OR ");
                    }
                    sb.append(colPath).append(" Like '%.").append(mediaInfo.extension).append('\'');
                    cnt++;
                }
                sb.append(" ) ) OR");
            }
            sb.append(" ( ").append(colMimeType).append(" NOT NULL AND ( ");

            int index = 0;
            for (String mimeType : mimeTypeList) {
                int starIndex = mimeType.indexOf('*');
                if (index != 0) {
                    sb.append(" OR ");
                }
                if (starIndex >= 0) {
                    mimeType = mimeType.substring(0, starIndex);
                    sb.append(colMimeType).append(" LIKE '").append(mimeType).append("%'");
                } else {
                    sb.append(colMimeType).append(" = '").append(mimeType).append('\'');
                }
                index++;
            }
            sb.append(" ) ) )");
        }

        if (extensionList != null && extensionList.length > 0) {
            if (sb.length() > 0) {
                sb.append(" OR ");
            }
            sb.append("((");
            cnt = 0;
            for (String extension : extensionList) {
                if (cnt != 0) {
                    sb.append(" OR ");
                }
                sb.append(colPath).append(" Like '%.").append(extension).append('\'');
                cnt++;
            }
            sb.append(')');

            if (!TextUtils.isEmpty(prefix)) {
                sb.append("AND ( ").append(colPath).append(" IS NOT NULL AND (( replace (").append(colPath)
                        .append(", rtrim(").append(colPath).append(", replace(").append(colPath)
                        .append(", '/', '')), '') ) LIKE '").append(prefix).append("%' ))");

            }
            sb.append(')');
        }

        if (startPath != null) {
            if (sb.length() > 0) {
                sb.append(" AND ");
            }
            //TODO HYL STORAGE ID (CONSTANT)  可能会有运行错误
            //sb.append('(').append(MediaStore.Files.FileColumns.SEM_STORAGE_ID);
            if (startPath.startsWith(AppConstants.StoragePath.EMULATED_ENTRY_FOLDER)) {
                sb.append(" = ").append(INTERNAL_STORAGE_ID).append(')');
            } else {
                sb.append(" NOT IN ( ").append(INTERNAL_STORAGE_ID).append(',')
                        .append(PRIVATE_STORAGE_ID).append(") )");
            }
        }

        if (colFormat != null) {
            if (sb.length() > 0) {
                sb.append(" AND ");
            }
            sb.append("( ").append(colFormat).append(" != ").append(FileType.FOLDER).append(" )");
        }

        Log.e(this, "filtered selection - " + sb.toString());
        return sb.toString();
    }

    public static String getDocumentSelection() {
        if (mDocumentSelection == null) {
            String[] whereArgs = MediaFile.getDocumentExtensions();
            int length = whereArgs.length;
            for (int i = 0; i < length; i++) {
                whereArgs[i] = "'%." + whereArgs[i] + "'";
            }

            final String pathColumn = CategoryDbTableInfo.getInstance().getColumnName(COLUMN_ID.PATH);
            final String formatColumn = CategoryDbTableInfo.getInstance().getColumnName(COLUMN_ID.FORMAT);
            StringBuilder sb = new StringBuilder();
            sb.append('(');
            for (int i = 0; i < length; i++) {
                if (i < length - 1) {
                    sb.append(pathColumn).append(" LIKE ").append(whereArgs[i]).append(" OR ");
                } else {
                    sb.append(pathColumn).append(" LIKE ").append(whereArgs[i]);
                }
            }
            sb.append(')').append(" AND ").append(formatColumn).append(" != ").append(FileType.FOLDER);
            mDocumentSelection = sb.toString();
        }
        return mDocumentSelection;
    }

    @Override
    public String[] getSelectionArgs() {
        ArrayList<String> selectionArgs = new ArrayList<>();
        if (mNavigationInfo.getMaxSelectCnt() == -1 && mNavigationInfo.getNavigationMode() == NavigationMode.Pick_files) {
            selectionArgs.add(AppConstants.StoragePath.PRIVATE_ROOT + "/%");
        }

        if (mBucketId != null) {
            selectionArgs.add(mBucketId);
        }

        if (selectionArgs.isEmpty())
            return null;
        else
            return selectionArgs.toArray(new String[selectionArgs.size()]);
    }

    @Override
    protected FileRecord _getFileRecord(Cursor cursor) {
        FileRecord ret = null;

        final int idIndex = mTableInfo.getIndex(COLUMN_ID.ID);
        final int pathIndex = mTableInfo.getIndex(COLUMN_ID.PATH);
        final int sizeIndex = mTableInfo.getIndex(COLUMN_ID.SIZE);
        final int dateIndex = mTableInfo.getIndex(COLUMN_ID.DATE);
        final int mimeTypeIndex = mTableInfo.getIndex(COLUMN_ID.MIME_TYPE);
        final int sefFileType = mTableInfo.getIndex(COLUMN_ID.SEF_FILE_TYPE);
        final int isGear360Video = mTableInfo.getIndex(COLUMN_ID.IS_360_VIDEO);
        boolean isGear360Contents = false;

        if (cursor != null && cursor.getCount() > 0) {
            try {
                int id = cursor.getInt(idIndex);
                String full_path = cursor.getString(pathIndex);
                String path = FileRecord.getPath(full_path);
                String name = FileRecord.getName(full_path);
                String mimeType = cursor.getString(mimeTypeIndex);
                long size = cursor.getLong(sizeIndex);
                long date = cursor.getLong(dateIndex) * 1000;
                int fileType = MediaFile.getFileType(full_path, mimeType);
                int isHidden = 0;
                int itemCount = 0;
                int itemCountHidden = 0;
                if (sefFileType >= 0) {
                    isGear360Contents = (cursor.getInt(sefFileType) == AppConstants.SEF_FILE_TYPE_GEAR_360_IMAGE);
                }
                if (!isGear360Contents && isGear360Video >= 0) {
                    isGear360Contents = (cursor.getInt(isGear360Video) == 1);
                }

                ret = FileRecord.createFileRecord(StorageType.Local, id, path, name, size, date, fileType, isHidden, itemCount, itemCountHidden);
                if (ret != null) {
                    ret.setMimeType(mimeType);
                    ret.setGear360Contents(isGear360Contents);
                }
            } catch (IllegalStateException e) {
                Log.e(this, "_getFileRecord() ] IllegalStateException:" + e.toString());
            } catch (CursorIndexOutOfBoundsException e) {
                Log.e(this, "_getFileRecord() ] CursorIndexOutOfBoundsException:" + e.toString());
            }
        }

        return ret;
    }

    @Override
    public String getFilePath(Cursor cursor) {
        return getFilePath(cursor, mTableInfo.getIndex(COLUMN_ID.PATH));
    }

    @Override
    public StorageType getStorageType() {
        return StorageType.Category;
    }

    protected CategoryType getCategoryType() {
        return CategoryFileRecord.getCategoryType(FileRecord.getFullPath(mCurRecord.getPath(), mCurRecord.getName()));
    }

    @Override
    protected void doFragmentLoadFinished(AbsMyFilesFragment fragment, Cursor data) {
        int curTotCnt = data.getCount();
        if (mPreTotCount != curTotCnt) {
            fragment.onLoadFinished();
        }

        mPreTotCount = curTotCnt;
    }

    @Override
    public boolean _isEnabled(int position) {
        return isCheckable(position);
    }
}
